/*******************************************************************
 *
 * @Version : 0.5 
 *
 * TestClient.java 
 *
 * 2010-11-15 上午11:35:21
 *
 *******************************************************************/
package game.breeze.socket;

import game.breeze.Breeze;
import game.breeze.message.AppMessage;
import game.breeze.message.Message;
import game.breeze.message.codec.AppMessageDecoder;
import game.breeze.message.codec.AppMessageEncoder;
import game.breeze.message.processor.SceneMessageProcessor;
import game.breeze.message.processor.WorldMessageProcessor;
import game.breeze.socket.connection.NetConnection;
import game.breeze.socket.connection.SimpleConnection;
import game.breeze.socket.connection.listener.NetConnectionListener;
import game.breeze.socket.server.listener.NetServerListener;
import game.breeze.socket.util.Utils;

import java.io.IOException;

/**
 * Class desc there
 * 
 * @author yangwei ywengineer@gmail.com
 * 
 */
public class SocketClient implements NetConnectionListener, NetServerListener, Runnable {
	private Breeze game;

	private TcpSocket socket;

	private SimpleConnection connection;

	private Thread runner;

	private boolean isRunning = false;

	public SocketClient(Breeze game, String ip, int port) throws IOException {
		socket = new TcpSocket(ip, port);

		connection = new SimpleConnection(socket);

		connection.setPingTime(1000);

		AppMessageDecoder decoder = new AppMessageDecoder();

		AppMessageEncoder encoder = new AppMessageEncoder();

		connection.setMessageDecoder(decoder);

		connection.setMessageEncoder(encoder);

		connection.addListener(this);

		connection.setMaxBufferSize(Integer.MAX_VALUE);

		this.game = game;
	}

	public void start() {
		if (isRunning) {
			return;
		}

		isRunning = true;

		if (runner == null) {
			runner = new Thread(this, "Socket Client");
			runner.start();
		}

		// CommonUtils.printSection("Client Started");
	}

	@Override
	public void messageArrived(NetConnection conn, Message msg) {
		AppMessage message = (AppMessage) msg;
		switch (message.getType()) {
		case AppMessage.MSG_WORLD:
			WorldMessageProcessor.getInstance().proccessMessage(game, message.getBuffer());
			break;
		case AppMessage.MSG_SCENE:
			SceneMessageProcessor.getInstance().proccessMessage(game, message.getBuffer());
			break;
		default:
			break;
		}
	}

	@Override
	public void run() {

		while (isRunning) {
			peek();
		}
	}

	public void sendMessage(Message msg) {
		if (isActive()) {
			connection.sendMessage(msg);
		}
	}

	public boolean isActive() {
		if (connection == null)
			return false;
		return connection.isActive();
	}

	public void peek() {
		// if(connection.hasData())
		Utils.sleep(10);

		if (connection == null)
			return;

		connection.processPeek();

		if (!connection.isActive()) {
			connectionClosed(connection);
		}
	}

	public void stop() {
		if (!isRunning || runner == null || runner.isInterrupted()) {
			return;
		}

		runner.interrupt();

		isRunning = false;

		connection.close();

		connection.setMessageDecoder(null);

		connection.setMessageEncoder(null);

		connection.removeAllListeners();

		connection = null;

		runner = null;

		game = null;

		System.out.println("Client Disconnected");
	}

	@Override
	public void connectionClosed(NetConnection connection) {
		stop();
	}

	@Override
	public void connectionOpened(NetConnection connection) {
	}
}
